package com.segersten.kalaha

import java.util.logging.Logger

class Board implements Serializable {
	
	static final Logger LOG = Logger.getLogger(Board.class.getCanonicalName())

	boolean player1
	boolean player2
	List buckets
	int stones
	
    static constraints = {
    	buckets(nullable:false)
	}
	
	def player1select = { int index ->
		return move(index,1,6)
	}
	
	def player2select = { int index ->
		return move(index,8,13)
	}
	
	public int getPlayer1score() {
		return buckets.subList(1,8).sum()
	}
	
	public int getPlayer2score() {
		return buckets.subList(8,14).sum() + buckets[0]
	}
	
	private static int[] OPPOSITES = [ -1, 13, 12, 11,  10,  9, 8, 
									   -1,  6,  5,  4,   3,  2, 1 ]
	
	def move = {int index, int startIndex, int endIndex ->
		//LOG.info("selected ${index} [${startIndex}-${endIndex}]")
		int homeIndex = (endIndex+1)%14
		int opponentHomeIndex = startIndex-1
		
		// selected wrong bucket 
		if ((startIndex..endIndex).contains(index)==false) {
			LOG.info("selected wrong bucket - ${index}")
			return ["nextPlayer":false, "gameFinished":false]
		}
		
		// move kulor
		int count = buckets[index]
		if (count==0) { 
			LOG.info("selected empty bucket - ${index}")
			return ["nextPlayer":false, "gameFinished":false] 
		}
		int bucketIndex = -1
		buckets[index] = 0
		int iter = index
		for (int i=index+1;i<=index+count; i++) {
			iter+=1
			if ((iter%14)==opponentHomeIndex) { LOG.info("Skipping on ${}iter}"); iter+=1 } // skip opponent home
			bucketIndex = iter % 14
			buckets[bucketIndex] += 1
		}
		
		// put last kula in own home bucket
		if ( bucketIndex==homeIndex ) {
			// do another round
			if (buckets.subList(startIndex,endIndex+1).sum()!=0) { 
				LOG.info("put last kula in own home bucket - do another round")
				return ["nextPlayer":false, "gameFinished":false] 
			}
			
			// check if game finished, otherwise let the other player move
			if (buckets[homeIndex] + buckets[opponentHomeIndex] == stones ) {
				LOG.info("put last kula in own home bucket - game finished")
				return ["nextPlayer":false, "gameFinished":true]
			} else { 
				LOG.info("put last kula in own home bucket - opponents turn")
				return ["nextPlayer":true, "gameFinished":false] 
			}
		}
		
		// take kulor from the opposite bucket
		if (buckets[bucketIndex]==1 && (startIndex..endIndex).contains(bucketIndex)==true) {
			int oppositeIndex = OPPOSITES[bucketIndex]
			if (buckets[oppositeIndex]>0) {
				buckets[homeIndex] += buckets[oppositeIndex]+1
				buckets[oppositeIndex] = 0
				buckets[bucketIndex] = 0
				LOG.info("take kulor from the opposite bucket ${bucketIndex}+${oppositeIndex}->${homeIndex}")
			}
		}
		
		// check if game finished
		if (buckets[homeIndex] + buckets[opponentHomeIndex] == stones ) {
			LOG.info("game finished")
			return ["nextPlayer":false, "gameFinished":true]
		}
		
		// check if oppenent can move
		if (buckets.subList(startIndex,endIndex+1).sum()+buckets[homeIndex] + buckets[opponentHomeIndex] == stones) { 
				LOG.info("oppenent can't move - do another round")
				return ["nextPlayer":false, "gameFinished":false] 
		}
		
		LOG.info("normal flow ${startIndex}-${endIndex} sum:${(startIndex..endIndex).sum()} - home:${buckets[homeIndex]} - opponent:${buckets[opponentHomeIndex]}")
		return ["nextPlayer":true, "gameFinished":false]
	}
	
	public String toString() {
		if (!buckets || buckets.size()!=14) return "null or unexpected size"
		return "  ${buckets[1]} ${buckets[2]} ${buckets[3]} ${buckets[4]} ${buckets[5]} ${buckets[6]}\n${buckets[0]}"+
		"            ${buckets[7]}\n  ${buckets[13]} ${buckets[12]} ${buckets[11]} ${buckets[10]} ${buckets[9]} ${buckets[8]}";
	}
	
}
